package cn.mw.cmdb.param;

import cn.hutool.core.util.StrUtil;
import cn.mw.cmdb.entity.AssetsScanResultInfo;
import cn.mw.cmdb.service.ServiceChoose;
import cn.mw.cmdb.service.impl.AssetsScanResultServiceImpl;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.SearchParam;
import cn.mw.components.mongodb.entity.SubCondition;
import com.google.common.base.Strings;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.data.mongodb.core.query.Criteria;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

@Data
@Schema(description = "资产实例扫描列表查询参数")
public class AssetsInstanceScanSearchParam extends SearchParam implements ServiceChoose, SearchParamConvert {

    @Schema(description = "模型ID")
    private String modelId;

    @Schema(description = "实例ID")
    private String id;

    @Schema(description = "扫描批次号")
    private Integer batchNo;

    @Schema(description = "ip地址")
    private String ipAddress;

    @Schema(description = "主机名称")
    private String hostName;

    @Schema(description = "品牌id")
    private String brandId;

    @Schema(description = "品牌")
    private String brand;

    private Boolean exist;

    @Schema(description = "描述")
    private String description;

    @Schema(description = "规则型号")
    private String specification;

    @Schema(description = "查询标识: noInsert/insert/fail", example = "noInsert")
    private String queryIdent;

    @Schema(description = "失败原因")
    private String failReason;

    @Override
    public void convert() {
        if (!Strings.isNullOrEmpty(getId())) {
            this.addSubCondition(CMDBTool.getFieldName(AssetsScanResultInfo::getId)
                    , new SubCondition(CriteriaOpsType.is.name(), getId()));
        }

    }

    @Override
    public String getServiceId() {
        return AssetsScanResultServiceImpl.ID;
    }

    public List<Criteria> generatorCriteria(String prefix) {
        List<Criteria> criteriaList = new ArrayList<>();
        prefix = prefix + ".";
        if (StrUtil.isNotBlank(ipAddress)) {
            criteriaList.add(createRegexCriteria(prefix, CMDBTool.getFieldName(AssetsInstanceScanSearchParam::getIpAddress), ipAddress));
        }
        if (StrUtil.isNotBlank(hostName)) {
            criteriaList.add(createRegexCriteria(prefix, CMDBTool.getFieldName(AssetsInstanceScanSearchParam::getHostName), hostName));
        }
        if (StrUtil.isNotBlank(description)) {
            criteriaList.add(createRegexCriteria(prefix, CMDBTool.getFieldName(AssetsInstanceScanSearchParam::getDescription), description));
        }
        if (StrUtil.isNotBlank(brand)) {
            criteriaList.add(createRegexCriteria(prefix, CMDBTool.getFieldName(AssetsInstanceScanSearchParam::getBrand), brand));
        }
        if (exist != null) {
            Criteria criteria = new Criteria(prefix + CMDBTool.getFieldName(AssetsInstanceScanSearchParam::getExist)).is(exist);
            criteriaList.add(criteria);
        }
        return criteriaList.stream().filter(Objects::nonNull).toList();
    }

    private Criteria createRegexCriteria(String prefix, String field, String value) {
        if (StrUtil.isNotBlank(value)) {
            Pattern pattern = Pattern.compile(regexCharacters(value), Pattern.CASE_INSENSITIVE);
            return new Criteria(prefix + field).regex(pattern);
        }
        return null;
    }

    public String regexCharacters(Object input) {
        String str = strValueConvert(input);
        // 特殊字符
        String[] specialCharacters = {"\\", "^", "$", ".", "|", "?", "*", "+", "(", ")", "[", "]", "{", "}"};
        StringBuilder patternBuilder = new StringBuilder();
        for (String character : specialCharacters) {
            patternBuilder.append("\\").append(character);
        }
        String regexPattern = patternBuilder.toString();
        // 字符串中特殊字符替换
        return str.replaceAll("[" + regexPattern + "]", "\\\\$0");
    }

    public static String strValueConvert(Object value) {
        if (value == null) {
            return "";
        }
        return value.toString();
    }
}
